package com.warm.demo.satoken;

import cn.dev33.satoken.stp.StpUtil;
import com.warm.core.domain.R;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.validation.annotation.Valid;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Sa-Token 权限认证示例
 *
 * @author warm
 */
@Valid
@Controller
@Mapping("/demo/testAuth")
public class TestAuthController {

    /**
     * 查询权限 ---- http://localhost:18080/demo/testAuth/getPermission 前提1：首先调用登录接口进行登录，代码在
     * com.pj.cases.use.LoginAuthController 中有详细解释，此处不再赘述 ----
     * http://localhost:18080/demo/testAuth/doLogin?name=zhang&pwd=123456
     * <p>
     * 前提2：项目实现 StpInterface 接口，代码在 StpInterfaceImpl Sa-Token 将从此实现类获取 每个账号拥有哪些权限。
     * <p>
     * 然后我们就可以使用以下示例中的代码进行鉴权了
     */
    @Mapping("getPermission")
    public R<Map<String, List<String>>> getPermission() {
        Map<String, List<String>> map = new HashMap<>();
        // 查询权限信息 ，如果当前会话未登录，会返回一个空集合
        List<String> permissionList = StpUtil.getPermissionList();
        System.out.println("当前登录账号拥有的所有权限：" + permissionList);

        // 查询角色信息 ，如果当前会话未登录，会返回一个空集合
        List<String> roleList = StpUtil.getRoleList();
        System.out.println("当前登录账号拥有的所有角色：" + roleList);

        map.put("roleList", roleList);
        map.put("permissionList", permissionList);
        // 返回给前端
        return R.ok(map);
    }

    /**
     * 权限校验 ---- http://localhost:18080/demo/testAuth/checkPermission
     *
     * @return
     */
    @Mapping("checkPermission")
    public R checkPermission() {

        // 判断：当前账号是否拥有一个权限，返回 true 或 false
        // 如果当前账号未登录，则永远返回 false
        StpUtil.hasPermission("user.add");
        StpUtil.hasPermissionAnd("user.add", "user.delete", "user.get"); // 指定多个，必须全部拥有才会返回 true
        StpUtil.hasPermissionOr("user.add", "user.delete", "user.get"); // 指定多个，只要拥有一个就会返回 true

        // 校验：当前账号是否拥有一个权限，校验不通过时会抛出 `NotPermissionException` 异常
        // 如果当前账号未登录，则永远校验失败
        StpUtil.checkPermission("user.add");
        StpUtil.checkPermissionAnd("user.add", "user.delete", "user.get"); // 指定多个，必须全部拥有才会校验通过
        StpUtil.checkPermissionOr("user.add", "user.delete", "user.get"); // 指定多个，只要拥有一个就会校验通过

        return R.ok();
    }

    /**
     * 角色校验 ---- http://localhost:18080/demo/testAuth/checkRole
     *
     * @return
     */
    @Mapping("checkRole")
    public R checkRole() {

        // 判断：当前账号是否拥有一个角色，返回 true 或 false
        // 如果当前账号未登录，则永远返回 false
        StpUtil.hasRole("admin");
        StpUtil.hasRoleAnd("admin", "ceo", "cfo"); // 指定多个，必须全部拥有才会返回 true
        StpUtil.hasRoleOr("admin", "ceo", "cfo"); // 指定多个，只要拥有一个就会返回 true

        // 校验：当前账号是否拥有一个角色，校验不通过时会抛出 `NotRoleException` 异常
        // 如果当前账号未登录，则永远校验失败
        StpUtil.checkRole("admin");
        StpUtil.checkRoleAnd("admin", "ceo", "cfo"); // 指定多个，必须全部拥有才会校验通过
        StpUtil.checkRoleOr("admin", "ceo", "cfo"); // 指定多个，只要拥有一个就会校验通过

        return R.ok();
    }

    /**
     * 权限通配符 ---- http://localhost:18080/demo/testAuth/wildcardPermission
     *
     * @return
     */
    @Mapping("wildcardPermission")
    public R wildcardPermission() {

        // 前提条件：在 StpInterface 实现类中，为账号返回了 "art.*" 泛权限
        StpUtil.hasPermission("art.add"); // 返回 true
        StpUtil.hasPermission("art.delete"); // 返回 true
        StpUtil.hasPermission("goods.add"); // 返回 false，因为前缀不符合

        // * 符合可以出现在任意位置，比如权限码的开头，当账号拥有 "*.delete" 时
        StpUtil.hasPermission("goods.add"); // false
        StpUtil.hasPermission("goods.delete"); // true
        StpUtil.hasPermission("art.delete"); // true

        // 也可以出现在权限码的中间，比如当账号拥有 "shop.*.user" 时
        StpUtil.hasPermission("shop.add.user"); // true
        StpUtil.hasPermission("shop.delete.user"); // true
        StpUtil.hasPermission("shop.delete.goods"); // false，因为后缀不符合

        // 注意点：
        // 1、上帝权限：当一个账号拥有 "*" 权限时，他可以验证通过任何权限码
        // 2、角色校验也可以加 * ，指定泛角色，例如： "*.admin"，暂不赘述

        return R.ok();
    }

}
